class LRUCache {
    typedef list<pair<int, int>>::iterator LIt;
public:
    LRUCache(int capacity) 
       :_cap(capacity)
    {}
    
    int get(int key) {
        auto pos = _mp.find(key);
        if(pos == _mp.end())
            return -1;
        
        LIt it = pos->second;
        _ls.splice(_ls.begin(), _ls, it);
        return it->second;
    }
    
    void put(int key, int value) {
        auto ret = _mp.find(key);
        if(ret == _mp.end())
        {
            if(_cap == _mp.size())
            {
                pair<int, int> bk = _ls.back();
                _mp.erase(bk.first);
                _ls.pop_back();
            }

            _ls.push_front(make_pair(key, value));
            _mp.insert({ key, _ls.begin() });
        }
        else
        {
            LIt it = ret->second;
            it->second = value;
            _ls.splice(_ls.begin(), _ls, it);
        }
    }
private:
    list<pair<int, int>> _ls;
    unordered_map<int, LIt> _mp;
    int _cap;
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */
